This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

source("./tianfengRwrappers.R")
# plan("multiprocess",workers = 8)

#冠状动脉

human_coronary_countmatrix <- read.csv("GSE131778_human_coronary_scRNAseq.txt", sep = "\t")
func <- function(s) {
  paste0(strsplit(s, ".", fixed = T)[[1]][2], "_", strsplit(s, ".", fixed = T)[[1]][1])
}
colnames(human_coronary_countmatrix) <- lapply(colnames(human_coronary_countmatrix), func) # 拆分样本

颈动脉斑块 CA dataset1

# 批量读取计数矩阵
# 需要把行名的gene删掉,用vscode修改
count_mats <- list.files("./CA_GSE155512")
count_mats <- count_mats[count_mats != "sampleinfo.txt"]
allList <- lapply(count_mats, function(folder) {
  CreateSeuratObject(
    counts = read.csv(paste0("./CA_GSE155512/", folder), sep = "\t"),
    project = folder, min.cells = 10, min.features = 300
  )
})
# 合并seurat对象
CA_dataset1 <- merge(allList[[1]],
  y = allList[-1], add.cell.ids = count_mats,
  project = "CA_dataset1"
)
rm(allList)

CA_dataset1 <- PercentageFeatureSet(CA_dataset1, pattern = "^MT-", col.name = "percent.mt") %>%
    subset(subset = nFeature_RNA > 600 & nFeature_RNA < 6000 & nCount_RNA > 1000 &  nCount_RNA < 30000) %>%
    SCTransform(vars.to.regress = "percent.mt", verbose = F) %>% 
    RunPCA() %>% FindNeighbors(dims = 1:20) %>% 
    RunUMAP(dims = 1:20) %>% 
    FindClusters(resolution = 0.1)

颈动脉斑块 CA dataset2

CA_dataset2 <- CreateSeuratObject(Read10X("./CA_GSE159677/"), names.field = 2, names.delim = "-",
                                     project = "CA_dataset2", min.cells = 10, min.features = 300) %>% 
    PercentageFeatureSet(pattern = "^MT-", col.name = "percent.mt") %>%
    subset(subset = nFeature_RNA > 600 & nFeature_RNA < 6000 & nCount_RNA > 1000 &  nCount_RNA < 30000) %>%
    SCTransform(vars.to.regress = "percent.mt", verbose = F) %>% 
    RunPCA() %>% FindNeighbors(dims = 1:20) %>% 
    RunUMAP(dims = 1:20) %>% 
    FindClusters(resolution = 0.1)

添加metadata samples存储完整信息,conditions按区域分,groups按病例分

Idents(human_coronary) <- human_coronary$orig.ident
Idents(human_coronary) <- c("1","1","2","2","3","3","4","4")
human_coronary$samples <- Idents(human_coronary)
Idents(human_coronary) <- human_coronary$seurat_clusters

Idents(CA_dataset2) <- CA_dataset2$orig.ident
CA_dataset2 <- RenameIdents(CA_dataset2,'1' = 'AC_1','2' = 'PA_1','3' = 'AC_2','4' = 'PA_2','5' = 'AC_3','6' = 'PA_3')
UMAPPlot(CA_dataset2)

CA_dataset2$sample <- Idents(CA_dataset2)
CA_dataset2 <- RenameIdents(CA_dataset2,'AC_1' = 'AC','PA_1' = 'PA','AC_2'= 'AC','PA_2'= 'PA','AC_3'= 'AC','PA_3'= 'PA')
CA_dataset2$conditions <- Idents(CA_dataset2)
Idents(CA_dataset2) <- CA_dataset2$orig.ident
CA_dataset2 <- RenameIdents(CA_dataset2, '1' = 'sp_1','2' = 'sp_1','3' = 'sp_2','4' = 'sp_2','5' = 'sp_3','6' = 'sp_3')
CA_dataset2$groups <- Idents(CA_dataset2)
Idents(CA_dataset2) <- CA_dataset2$seurat_clusters

保存结果

saveRDS(human_coronary,"human_coronary.rds")
saveRDS(CA_dataset1,"CA_dataset1.rds")
saveRDS(CA_dataset2,"CA_dataset2.rds") #已经经过分组处理了

读取结果

human_coronary <- readRDS("human_coronary.rds")
CA_dataset1 <- readRDS("CA_dataset1.rds")
CA_dataset2 <- readRDS("CA_dataset2.rds") #已经经过分组处理了

修改分群

基质细胞分类

ECs亚群分析 整合

整合算法可能出现负值,运行SCENIC时舍弃了这些异常值

# 提取内皮细胞亚群
ECs_list <- list(subset(CA_dataset1, idents = "Endothelial"), subset(human_coronary, idents = "Endothelial"))

ECs_list <- lapply(X = ECs_list, FUN = function(x) {
  x <- NormalizeData(x)
  x <- FindVariableFeatures(x, selection.method = "vst", nfeatures = 2000)
})
# 需要分析的差异基因
int_features <- SelectIntegrationFeatures(object.list = ECs_list)
# 选择合并的anchor特征
int_anchors <- FindIntegrationAnchors(object.list = ECs_list, anchor.features = int_features)

# 根据anchor合并
ECs_combined <- IntegrateData(anchorset = int_anchors)

DefaultAssay(ECs_combined) <- "integrated"
rm("ECs_list", "int_features", "int_anchors")
multi_featureplot(c("TNFRSF11B","ACTA2","CNN1","LUM"),human_coronary)

multi_featureplot(c("TNFRSF11B","ACTA2","CNN1","LUM"),CA_dataset1)

multi_featureplot(c("TNFRSF11B","ACTA2","CNN1","LUM"),CA_dataset2)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIAoKYGBge3J9CnNvdXJjZSgiLi90aWFuZmVuZ1J3cmFwcGVycy5SIikKIyBwbGFuKCJtdWx0aXByb2Nlc3MiLHdvcmtlcnMgPSA4KQpgYGAKCiPlhqDnirbliqjohIkKCmBgYHtyfQpodW1hbl9jb3JvbmFyeV9jb3VudG1hdHJpeCA8LSByZWFkLmNzdigiR1NFMTMxNzc4X2h1bWFuX2Nvcm9uYXJ5X3NjUk5Bc2VxLnR4dCIsIHNlcCA9ICJcdCIpCmZ1bmMgPC0gZnVuY3Rpb24ocykgewogIHBhc3RlMChzdHJzcGxpdChzLCAiLiIsIGZpeGVkID0gVClbWzFdXVsyXSwgIl8iLCBzdHJzcGxpdChzLCAiLiIsIGZpeGVkID0gVClbWzFdXVsxXSkKfQpjb2xuYW1lcyhodW1hbl9jb3JvbmFyeV9jb3VudG1hdHJpeCkgPC0gbGFwcGx5KGNvbG5hbWVzKGh1bWFuX2Nvcm9uYXJ5X2NvdW50bWF0cml4KSwgZnVuYykgIyDmi4bliIbmoLfmnKwKYGBgCgpgYGB7cn0KaHVtYW5fY29yb25hcnkgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IGh1bWFuX2Nvcm9uYXJ5X2NvdW50bWF0cml4LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2plY3QgPSAiaHVtYW5fY29yb25hcnkiLCBtaW4uY2VsbHMgPSAxMCwgbWluLmZlYXR1cmVzID0gMzAwKSAlPiUgCiAgICBQZXJjZW50YWdlRmVhdHVyZVNldChwYXR0ZXJuID0gIl5NVC0iLCBjb2wubmFtZSA9ICJwZXJjZW50Lm10IikgJT4lCiAgICBzdWJzZXQoc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gNjAwICYgbkZlYXR1cmVfUk5BIDwgNjAwMCAmIG5Db3VudF9STkEgPiAxMDAwICYgIG5Db3VudF9STkEgPCAzMDAwMCkgJT4lCiAgICBTQ1RyYW5zZm9ybSh2YXJzLnRvLnJlZ3Jlc3MgPSAicGVyY2VudC5tdCIsIHZlcmJvc2UgPSBGKSAlPiUgCiAgICBSdW5QQ0EoKSAlPiUgRmluZE5laWdoYm9ycyhkaW1zID0gMToyMCkgJT4lIAogICAgUnVuVU1BUChkaW1zID0gMToyMCkgJT4lIAogICAgRmluZENsdXN0ZXJzKHJlc29sdXRpb24gPSAwLjEpCnJtKGh1bWFuX2Nvcm9uYXJ5X2NvdW50bWF0cml4KQpmKCJQTFZBUCIsaHVtYW5fY29yb25hcnkpCmBgYAoKCiMg6aKI5Yqo6ISJ5paR5Z2XIENBIGRhdGFzZXQxCmBgYHtyfQojIOaJuemHj+ivu+WPluiuoeaVsOefqemYtQojIOmcgOimgeaKiuihjOWQjeeahGdlbmXliKDmjonvvIznlKh2c2NvZGXkv67mlLkKY291bnRfbWF0cyA8LSBsaXN0LmZpbGVzKCIuL0NBX0dTRTE1NTUxMiIpCmNvdW50X21hdHMgPC0gY291bnRfbWF0c1tjb3VudF9tYXRzICE9ICJzYW1wbGVpbmZvLnR4dCJdCmFsbExpc3QgPC0gbGFwcGx5KGNvdW50X21hdHMsIGZ1bmN0aW9uKGZvbGRlcikgewogIENyZWF0ZVNldXJhdE9iamVjdCgKICAgIGNvdW50cyA9IHJlYWQuY3N2KHBhc3RlMCgiLi9DQV9HU0UxNTU1MTIvIiwgZm9sZGVyKSwgc2VwID0gIlx0IiksCiAgICBwcm9qZWN0ID0gZm9sZGVyLCBtaW4uY2VsbHMgPSAxMCwgbWluLmZlYXR1cmVzID0gMzAwCiAgKQp9KQojIOWQiOW5tnNldXJhdOWvueixoQpDQV9kYXRhc2V0MSA8LSBtZXJnZShhbGxMaXN0W1sxXV0sCiAgeSA9IGFsbExpc3RbLTFdLCBhZGQuY2VsbC5pZHMgPSBjb3VudF9tYXRzLAogIHByb2plY3QgPSAiQ0FfZGF0YXNldDEiCikKcm0oYWxsTGlzdCkKCkNBX2RhdGFzZXQxIDwtIFBlcmNlbnRhZ2VGZWF0dXJlU2V0KENBX2RhdGFzZXQxLCBwYXR0ZXJuID0gIl5NVC0iLCBjb2wubmFtZSA9ICJwZXJjZW50Lm10IikgJT4lCiAgICBzdWJzZXQoc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gNjAwICYgbkZlYXR1cmVfUk5BIDwgNjAwMCAmIG5Db3VudF9STkEgPiAxMDAwICYgIG5Db3VudF9STkEgPCAzMDAwMCkgJT4lCiAgICBTQ1RyYW5zZm9ybSh2YXJzLnRvLnJlZ3Jlc3MgPSAicGVyY2VudC5tdCIsIHZlcmJvc2UgPSBGKSAlPiUgCiAgICBSdW5QQ0EoKSAlPiUgRmluZE5laWdoYm9ycyhkaW1zID0gMToyMCkgJT4lIAogICAgUnVuVU1BUChkaW1zID0gMToyMCkgJT4lIAogICAgRmluZENsdXN0ZXJzKHJlc29sdXRpb24gPSAwLjEpCgpgYGAKCgojIOmiiOWKqOiEieaWkeWdlyBDQSBkYXRhc2V0MgpgYGB7cn0KQ0FfZGF0YXNldDIgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KFJlYWQxMFgoIi4vQ0FfR1NFMTU5Njc3LyIpLCBuYW1lcy5maWVsZCA9IDIsIG5hbWVzLmRlbGltID0gIi0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvamVjdCA9ICJDQV9kYXRhc2V0MiIsIG1pbi5jZWxscyA9IDEwLCBtaW4uZmVhdHVyZXMgPSAzMDApICU+JSAKICAgIFBlcmNlbnRhZ2VGZWF0dXJlU2V0KHBhdHRlcm4gPSAiXk1ULSIsIGNvbC5uYW1lID0gInBlcmNlbnQubXQiKSAlPiUKICAgIHN1YnNldChzdWJzZXQgPSBuRmVhdHVyZV9STkEgPiA2MDAgJiBuRmVhdHVyZV9STkEgPCA2MDAwICYgbkNvdW50X1JOQSA+IDEwMDAgJiAgbkNvdW50X1JOQSA8IDMwMDAwKSAlPiUKICAgIFNDVHJhbnNmb3JtKHZhcnMudG8ucmVncmVzcyA9ICJwZXJjZW50Lm10IiwgdmVyYm9zZSA9IEYpICU+JSAKICAgIFJ1blBDQSgpICU+JSBGaW5kTmVpZ2hib3JzKGRpbXMgPSAxOjIwKSAlPiUgCiAgICBSdW5VTUFQKGRpbXMgPSAxOjIwKSAlPiUgCiAgICBGaW5kQ2x1c3RlcnMocmVzb2x1dGlvbiA9IDAuMSkKYGBgCgoKIyDmt7vliqBtZXRhZGF0YSBzYW1wbGVz5a2Y5YKo5a6M5pW05L+h5oGv77yMY29uZGl0aW9uc+aMieWMuuWfn+WIhu+8jGdyb3Vwc+aMieeXheS+i+WIhgpgYGB7cn0KSWRlbnRzKGh1bWFuX2Nvcm9uYXJ5KSA8LSBodW1hbl9jb3JvbmFyeSRvcmlnLmlkZW50CklkZW50cyhodW1hbl9jb3JvbmFyeSkgPC0gYygiMSIsIjEiLCIyIiwiMiIsIjMiLCIzIiwiNCIsIjQiKQpodW1hbl9jb3JvbmFyeSRzYW1wbGVzIDwtIElkZW50cyhodW1hbl9jb3JvbmFyeSkKSWRlbnRzKGh1bWFuX2Nvcm9uYXJ5KSA8LSBodW1hbl9jb3JvbmFyeSRzZXVyYXRfY2x1c3RlcnMKCklkZW50cyhDQV9kYXRhc2V0MikgPC0gQ0FfZGF0YXNldDIkb3JpZy5pZGVudApDQV9kYXRhc2V0MiA8LSBSZW5hbWVJZGVudHMoQ0FfZGF0YXNldDIsJzEnID0gJ0FDXzEnLCcyJyA9ICdQQV8xJywnMycgPSAnQUNfMicsJzQnID0gJ1BBXzInLCc1JyA9ICdBQ18zJywnNicgPSAnUEFfMycpClVNQVBQbG90KENBX2RhdGFzZXQyKQoKQ0FfZGF0YXNldDIkc2FtcGxlIDwtIElkZW50cyhDQV9kYXRhc2V0MikKQ0FfZGF0YXNldDIgPC0gUmVuYW1lSWRlbnRzKENBX2RhdGFzZXQyLCdBQ18xJyA9ICdBQycsJ1BBXzEnID0gJ1BBJywnQUNfMic9ICdBQycsJ1BBXzInPSAnUEEnLCdBQ18zJz0gJ0FDJywnUEFfMyc9ICdQQScpCkNBX2RhdGFzZXQyJGNvbmRpdGlvbnMgPC0gSWRlbnRzKENBX2RhdGFzZXQyKQpJZGVudHMoQ0FfZGF0YXNldDIpIDwtIENBX2RhdGFzZXQyJG9yaWcuaWRlbnQKQ0FfZGF0YXNldDIgPC0gUmVuYW1lSWRlbnRzKENBX2RhdGFzZXQyLCAnMScgPSAnc3BfMScsJzInID0gJ3NwXzEnLCczJyA9ICdzcF8yJywnNCcgPSAnc3BfMicsJzUnID0gJ3NwXzMnLCc2JyA9ICdzcF8zJykKQ0FfZGF0YXNldDIkZ3JvdXBzIDwtIElkZW50cyhDQV9kYXRhc2V0MikKSWRlbnRzKENBX2RhdGFzZXQyKSA8LSBDQV9kYXRhc2V0MiRzZXVyYXRfY2x1c3RlcnMKYGBgCgojIOS/neWtmOe7k+aenApgYGB7cn0Kc2F2ZVJEUyhodW1hbl9jb3JvbmFyeSwiaHVtYW5fY29yb25hcnkucmRzIikKc2F2ZVJEUyhDQV9kYXRhc2V0MSwiQ0FfZGF0YXNldDEucmRzIikKc2F2ZVJEUyhDQV9kYXRhc2V0MiwiQ0FfZGF0YXNldDIucmRzIikgI+W3sue7j+e7j+i/h+WIhue7hOWkhOeQhuS6hgpgYGAKCi0tLS0KIyDor7vlj5bnu5PmnpwKYGBge3J9Cmh1bWFuX2Nvcm9uYXJ5IDwtIHJlYWRSRFMoImh1bWFuX2Nvcm9uYXJ5LnJkcyIpCkNBX2RhdGFzZXQxIDwtIHJlYWRSRFMoIkNBX2RhdGFzZXQxLnJkcyIpCkNBX2RhdGFzZXQyIDwtIHJlYWRSRFMoIkNBX2RhdGFzZXQyLnJkcyIpICPlt7Lnu4/nu4/ov4fliIbnu4TlpITnkIbkuoYKYGBgCgojIyDkv67mlLnliIbnvqQKYGBge3J9CnVtYXBwbG90KENBX2RhdGFzZXQyLCBzcGxpdC5ieSA9ICJzYW1wbGUiKQp1bWFwcGxvdChDQV9kYXRhc2V0Mixncm91cC5ieSA9ICJncm91cHMiLCBzcGxpdC5ieSA9ICJjb25kaXRpb25zIikKbXVsdGlfZmVhdHVyZXBsb3QoYygiSEVZMSIsIkdKQTUiLCJTRU1BM0ciLCJDWENMMTIiLCJTT1gxNyIsIkNESDUiLCJQRUNBTTEiKSxDQV9kYXRhc2V0MikKbXVsdGlfZmVhdHVyZXBsb3QoYygiQUNLUjEiLCJQTFZBUCIsIklUR0E2IiwiUEVDQU0xIiksQ0FfZGF0YXNldDIpCmBgYApgYGB7cn0KIyB0YWJsZShDQV9kYXRhc2V0MiRzYW1wbGUpCgojIOWFs+azqGNsdXN0ZXIgMy02IEVDCiMgY2x1c3RlciA3IOWfuui0qOe7huiDngoKbXVsdGlfZmVhdHVyZXBsb3QoYygiTFlaIiwiUFRQUkMiLCJDRDY5IiwiRVBDQU0iLCJDREgxIiwiUERHRlJCIiwiQ09MMUEyIiwiUEVDQU0xIiwiQ0xETjUiKSxDQV9kYXRhc2V0MikKCkRvdHBsb3QoYygiTFVNIiwiTU1QMiIsIk1HUCIsIkRDTiIsIk1ZSDExIiwiQUNUQTIiLCJDTk4xIiwiVEFHTE4iKSxDQV9kYXRhc2V0MikgI2NsdXN0ZXIgNyDnu4bog57lj6/ku6XooqvorqTkuLrmmK9tb2R1bGF0ZWQgU01DcwpDQV9kYXRhc2V0MiA8LSBBZGRNb2R1bGVTY29yZShDQV9kYXRhc2V0MixsaXN0KGMoIkxVTSIsIk1NUDIiLCJNR1AiLCJEQ04iKSkpCkNBX2RhdGFzZXQyIDwtIEFkZE1vZHVsZVNjb3JlKENBX2RhdGFzZXQyLGxpc3QoYygiTVlIMTEiLCJBQ1RBMiIsIkNOTjEiLCJUQUdMTiIpKSkKbXVsdGlfZmVhdHVyZXBsb3QoYygiQ2x1c3RlcjEiLCJMVU0iLCJBQ1RBMiIsIlRBR0xOIiksQ0FfZGF0YXNldDIpCm11bHRpX2ZlYXR1cmVwbG90KGMoIk1NUDIiLCJHSkE0IiwiUEVDQU0xIiwiQUNLUjEiKSwgQ0FfZGF0YXNldDIpCm11bHRpX2ZlYXR1cmVwbG90KGMoIk1NUDIiLCJHSkE0IiwiUEVDQU0xIiwiQUNLUjEiKSwgaHVtYW5fY29yb25hcnkpCgpgYGAKIyDln7rotKjnu4bog57liIbnsbsKYGBge3J9Cm11bHRpX2ZlYXR1cmVwbG90KGMoIkxZWiIsIlBUUFJDIiwiQ0Q2OSIsIlBER0ZSQiIsIkNPTDFBMiIsIlBFQ0FNMSIsIkNMRE41IiksIGh1bWFuX2Nvcm9uYXJ5KQptdWx0aV9mZWF0dXJlcGxvdChjKCJBQ1RBMiIsIkZOMSIpLGh1bWFuX2Nvcm9uYXJ5KQp1bWFwcGxvdChodW1hbl9jb3JvbmFyeSkKZHMwIDwtIHN1YnNldChodW1hbl9jb3JvbmFyeSwgaWRlbnRzID0gYygnMCcsJzMnLCc0JykpICAjaHVtYW5fY29yIOmAieaLqTAgMyA0ICBDQV9kYXRhc2V0MSDpgInmi6kw77yMNOS9nOS4uuWfuui0qOe7huiDniBDQV9kYXRhc2V0MiDpgInmi6k35ZKMMuS9nOS4uuWfuui0qOe7huiDngojQ0FfZGF0YXNldDIg6YCJ5oupN+WSjDLkvZzkuLrln7rotKjnu4bog54KdW1hcHBsb3QoZHMwLHNwbGl0LmJ5ID0gInNhbXBsZXMiKQoKCnNhdmVSRFMoZHMwLCJkczAucmRzIikKCnNhdmVSRFMoZHMxLCJkczEucmRzIikKCmBgYAoKCgojIEVDc+S6mue+pOWIhuaekCDmlbTlkIgKIyMg5pW05ZCI566X5rOV5Y+v6IO95Ye6546w6LSf5YC877yM6L+Q6KGMU0NFTklD5pe26IiN5byD5LqG6L+Z5Lqb5byC5bi45YC8CmBgYHtyfQojIOaPkOWPluWGheearue7huiDnuS6mue+pApFQ3NfbGlzdCA8LSBsaXN0KHN1YnNldChDQV9kYXRhc2V0MSwgaWRlbnRzID0gIkVuZG90aGVsaWFsIiksIHN1YnNldChodW1hbl9jb3JvbmFyeSwgaWRlbnRzID0gIkVuZG90aGVsaWFsIikpCgpFQ3NfbGlzdCA8LSBsYXBwbHkoWCA9IEVDc19saXN0LCBGVU4gPSBmdW5jdGlvbih4KSB7CiAgeCA8LSBOb3JtYWxpemVEYXRhKHgpCiAgeCA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyh4LCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCn0pCiMg6ZyA6KaB5YiG5p6Q55qE5beu5byC5Z+65ZugCmludF9mZWF0dXJlcyA8LSBTZWxlY3RJbnRlZ3JhdGlvbkZlYXR1cmVzKG9iamVjdC5saXN0ID0gRUNzX2xpc3QpCiMg6YCJ5oup5ZCI5bm255qEYW5jaG9y54m55b6BCmludF9hbmNob3JzIDwtIEZpbmRJbnRlZ3JhdGlvbkFuY2hvcnMob2JqZWN0Lmxpc3QgPSBFQ3NfbGlzdCwgYW5jaG9yLmZlYXR1cmVzID0gaW50X2ZlYXR1cmVzKQoKIyDmoLnmja5hbmNob3LlkIjlubYKRUNzX2NvbWJpbmVkIDwtIEludGVncmF0ZURhdGEoYW5jaG9yc2V0ID0gaW50X2FuY2hvcnMpCgpEZWZhdWx0QXNzYXkoRUNzX2NvbWJpbmVkKSA8LSAiaW50ZWdyYXRlZCIKcm0oIkVDc19saXN0IiwgImludF9mZWF0dXJlcyIsICJpbnRfYW5jaG9ycyIpCmBgYAoKCmBgYHtyfQptdWx0aV9mZWF0dXJlcGxvdChjKCJUTkZSU0YxMUIiLCJBQ1RBMiIsIkNOTjEiLCJMVU0iKSxodW1hbl9jb3JvbmFyeSkKbXVsdGlfZmVhdHVyZXBsb3QoYygiVE5GUlNGMTFCIiwiQUNUQTIiLCJDTk4xIiwiTFVNIiksQ0FfZGF0YXNldDEpCm11bHRpX2ZlYXR1cmVwbG90KGMoIlRORlJTRjExQiIsIkFDVEEyIiwiQ05OMSIsIkxVTSIpLENBX2RhdGFzZXQyKQpgYGAKCgoK